# pymq - The python based Message Queue
#
# Copyright(C) 2010, Dhruv Matani(dhuvbird@gmail.com)
#
# pymq is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# pymq is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with pymq. If not, see
# <http://www.gnu.org/licenses/>.
#

import threading
import socket
import logging
import config
import queue_globals as vars


class request_and_response_enqueuer(object):
    def __init__(self):
        self.lock = threading.Lock()
        self.sock = None
        self.sending = False
        self.intrReqString = "GET /_ah/processQueue/ HTTP/1.1\r\nHost: %s\r\nConnection: keep-alive\r\n\r\n" % config.HOSTNAME

    def connect_to_server(self, host, port):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((host, port))
        return sock

    def enqueue_entity(self, entity, inQueue):
        rhLock = vars.request_handler.lock
        rhLock.acquire()
        sendNotification = False

        try:
            pendingQueue  = getattr(vars.request_handler, inQueue)
            sendNotification = (len(pendingQueue) == 0)

            if not sendNotification:
                logging.debug("Not sending notification")
            pendingQueue.append(entity)
        except Exception, e:
            print "Exception (%s) while enqueuing entity" % str(e)
        finally:
            rhLock.release()

        if sendNotification:
            self.signal_asyncore_loop()

    def enqueue_request(self, request):
        self.enqueue_entity(request, "pendingRequests")

    def enqueue_response(self, response):
        self.enqueue_entity(response, "pendingResponses")

    def signal_asyncore_loop(self):
        justConnected = False
        # Send an HTTP request to localhost, telling it
        # to process responses. Use double-checked-locking (below)
        if self.sending == True:
            return
        if self.lock.acquire(False) == False:
            return
        if self.sending == True:
            self.lock.release()
            return
        self.sending = True
        try:
            if self.sock is None:
                # We connect to the server the first time we have a response to send
                print "connecting to port: %s" % config.PORT
                self.sock = self.connect_to_server(config.HOSTNAME, config.PORT)
                justConnected = True
            try:
                if justConnected:
                    bytesSent = self.sock.send(self.intrReqString)
                bytesSent = self.sock.send("d")
            except Exception, e:
                print "Caught exception (%s) in response_enqueuer::__call__" % str(e)
                self.sock = None
        except Exception, e:
            print "Error while connecting to the server"
        finally:
            self.sending = False
            self.lock.release()

